/*
 * MIT License
 *
 * Copyright (c) 2024 恩爸编程
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.enba.boot.core.base;

import com.alibaba.fastjson.JSON;
import com.enba.boot.core.enums.StatusEnum;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import lombok.Getter;
import lombok.Setter;

@ApiModel(value = "Result", description = "统一接口出参")
@Getter
public class Result<T> {

  private static final long serialVersionUID = 1L;

  @ApiModelProperty("状态码")
  private final Integer code;

  @ApiModelProperty("数据")
  private final T data;

  @ApiModelProperty("描述")
  private final String msg;

  @Setter
  @ApiModelProperty("data长度")
  private Long count;

  // 用注解指定构造函数及参数对应关系
  @JsonCreator
  public Result(
      @JsonProperty("code") Integer code,
      @JsonProperty("message") String msg,
      @JsonProperty("data") T data) {
    this.code = code;
    this.msg = msg;
    this.data = data;

    if (data == null) {
      this.count = 0L;
    } else if (data instanceof Collection) {
      this.count = (long) ((Collection<?>) data).size();
    } else if (data instanceof Map) {
      this.count = (long) ((Map<?, ?>) data).size();
    } else {
      this.count = 1L;
    }
  }

  /**
   * 分页
   *
   * @param data 分页数据
   * @param count 总数
   * @param <T> 泛型
   * @return Result
   */
  public static <T> Result<T> pageSuccess(T data, Long count) {
    Result<T> tResult =
        new Result<>(StatusEnum.SUCCESS.getCode(), StatusEnum.SUCCESS.getMsg(), data);
    tResult.setCount(count);
    return tResult;
  }

  public static <T> Result<T> success(Integer code, String msg, T data) {
    return new Result<T>(code, msg, data);
  }

  public static <T> Result<T> success() {
    return new Result<T>(StatusEnum.SUCCESS.getCode(), StatusEnum.SUCCESS.getMsg(), null);
  }

  public static <T> Result<T> success(T data) {
    return new Result<T>(StatusEnum.SUCCESS.getCode(), StatusEnum.SUCCESS.getMsg(), data);
  }

  public static <T> Result<T> err() {
    return new Result<T>(StatusEnum.ERR.getCode(), StatusEnum.ERR.getMsg(), null);
  }

  public static <T> Result<T> err(Integer code, String message) {
    return new Result<T>(code, message, null);
  }

  public static <T> Result<T> err(StatusEnum status) {
    return new Result<T>(status.getCode(), status.getMsg(), null);
  }

  public static <T> void render(HttpServletResponse response, Result<T> result) throws IOException {
    response.setContentType("application/json;charset=UTF-8");
    OutputStream out = response.getOutputStream();
    String str = JSON.toJSONString(result);
    out.write(str.getBytes(StandardCharsets.UTF_8));
    out.flush();
    out.close();
  }

  public static void render(HttpServletResponse response, String content) throws IOException {
    response.setContentType("text/html;charset=UTF-8");
    OutputStream out = response.getOutputStream();
    out.write(content.getBytes(StandardCharsets.UTF_8));
    out.flush();
    out.close();
  }
}
